package cn.zniot.so.zniotcore;

import cn.zniot.so.application.util.NumberTools;
import cn.zniot.so.transport.asynpack.AsynPacket;
import cn.zniot.so.transport.asynpack.HBPacketD;
import cn.zniot.so.transport.asynpack.LogicPacketC;
import cn.zniot.so.transport.asynpack.Zniot2ControlPacketD;
import cn.zniot.so.transport.asynpack.Zniot2PacketC;
import cn.zniot.so.transport.exception.NetException;

import org.apache.log4j.Logger;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolEncoderAdapter;
import org.apache.mina.filter.codec.ProtocolEncoderOutput;


/**
 * 盒子终端编码器
 */
public class ZniotEncoder extends ProtocolEncoderAdapter {
	private static Logger logger = Logger.getLogger(ZniotEncoder.class);
	private SendCommand sc;
	private CentCommand ccmd;

	
	public ZniotEncoder()
	{
		super();
		sc = new SendCommand();
		ccmd = new CentCommand();
	}

	@Override
	public void encode(IoSession session, Object message,
			ProtocolEncoderOutput out) throws Exception {
		AsynPacket packet = (AsynPacket) message;
		byte[] data = this.encode(packet);
		IoBuffer buffer = IoBuffer.allocate(data.length, false);
		buffer.setAutoExpand(true);
		buffer.setAutoShrink(true);
		buffer.put(data);
		buffer.flip();
		out.write(buffer);
	}

	private byte[] encode(AsynPacket packet) {
		
		if (packet instanceof LogicPacketC) {
			// 逻辑控制报文
			LogicPacketC p = (LogicPacketC) packet;
//			if (logger.isDebugEnabled()) {
//			    logger.debug("Encode logicpacketc -- " + p.getCommand());
//			}
			return p.getCommand();
		}  else if (packet instanceof HBPacketD) {
			// 心跳报文
			byte[] heartBreak = ((HBPacketD) packet).getHeartBreak();
			return heartBreak;
		} else if (packet instanceof Zniot2PacketC) {
		    //客户端连接上的监听
		    Zniot2PacketC Zniot2PacketC=(Zniot2PacketC) packet;
			return Zniot2PacketC.getbyteCode();
		}else if (packet instanceof Zniot2ControlPacketD) {
			Zniot2ControlPacketD zniot2ControlPacketD=(Zniot2ControlPacketD)packet;
			return zniot2ControlPacketD.getbyteCode();
		}
		return sc.content;
	}

	/**
	 * 16进制转换成10进制
	 */
	private int convertNum(String mctl) {
		int num = 0;
		if (mctl.length() == 4) {
			int int1 = Integer.valueOf(mctl.substring(0, 2), 16);
			int int2 = Integer.valueOf(mctl.substring(2, 4), 16);
			num = int1 * 256 + int2;
		} else if (mctl.length() == 2) {
			int int1 = Integer.valueOf(mctl.substring(0, 2), 16);
			num = int1;
		}
		return num;
	}

	/**
	 * 把硬件协议报文，最后封装成SendCommand结构 ---GPRS
	 * @param sc SendCommand：代入并且需要被设置的SendCommand结构对象
	 * @param ccmd CentCommand：硬件协议报文
	 */
	private void packSendComzandGPRS(SendCommand sc, CentCommand ccmd)
			throws NetException {
		if (sc == null)
			throw new NetException("SendCommand hasn't been created!");
		if (sc.id == null)
			throw new NetException("SendCommand's commAddr hasn't been initialized!");
		if (ccmd == null)
			throw new NetException("CentCommand hasn't been create!");
		ccmd.id = sc.id;
		sc.content = prepareSendPack(ccmd);
		sc.sendLen = ccmd.cmdlen;

		String hexString = NumberTools.conv2HexString(sc.content);
		if (logger.isDebugEnabled()) {
		    logger.debug("send(gprs) to:" + sc.id + " len:" + sc.sendLen
		            + " content:" + hexString);
        }

		return;
	}

	/**
	 * 追加消息的头和尾
	 */
	public byte[] prepareSendPack(CentCommand ccmd) {
		byte[] tmp = new byte[512];
		// pack sms packet
		byte[] cmdContent = new byte[256];
		// pack gprs packet
		// //26484558 2c00 0100 0000 0000 7534
		int pos = 0;
		// 包头
		tmp[pos++] = 0x26; // &
		tmp[pos++] = 0x48; // H
		tmp[pos++] = 0x45; // e
		tmp[pos++] = 0x58; // x
		// 包长度,先占位
		tmp[pos++] = (byte) 0xff;
		tmp[pos++] = (byte) 0x00;
		// 包序号，子包总数，子包序号，包类型
		tmp[pos++] = 0x01;
		tmp[pos++] = 0x00;

		tmp[pos++] = 0x00;
		tmp[pos++] = 0x00;

		tmp[pos++] = 0x00;
		tmp[pos++] = 0x00;

		tmp[pos++] = 0x34;
		tmp[pos++] = 0x75;
		// user data
		int cmdlen = prepareContentPack(ccmd, cmdContent);
		// 设置长度位
		tmp[4] = (byte) (cmdlen + 18);
		for (int i = 0; i < cmdlen; i++) {
			tmp[pos++] = cmdContent[i];
		}
		tmp[pos++] = (byte) 0xff;
		tmp[pos++] = (byte) 0xff;
		tmp[pos++] = 0x0D;
		tmp[pos++] = 0x0a;
		ccmd.cmd = new byte[pos];
		for (int i = 0; i < pos; i++) {
			ccmd.cmd[i] = tmp[i];
		}
		ccmd.cmdlen = pos;
		return ccmd.cmd;
	}

	/**
	 * 打包sms信息帧
	 */
	private int prepareContentPack(CentCommand ccmd, byte[] idcmd) {
		// id(20)+userdata(n)
		int pos = 0;
		// id code
		pos = NumberTools.fillContentWithFixLen(idcmd, ccmd.id.getBytes(), 20,
				0x20, pos);
		// user data
		for (int i = 0; i < ccmd.userdatalen; i++) {
			idcmd[pos++] = ccmd.userdata[i];
		}
		return pos;
	}

	/**
	 * 中心下发命令结构
	 */
	public class CentCommand {
		public int opertype;
		public int datatype;
		public int gprstype;
		public byte[] userdata = new byte[256];
		public int userdatalen;

		public String id;
		public byte[] cmd;
		public int cmdlen;
	}

	/**
	 * 发往车机的数据结构
	 */
	public class SendCommand {
		public String id;// 通信地址
		public byte[] content;// 发送的数据内容
		public int sendLen;// 数据内容长度
	}

//	/**
//	 * 内部测试接口
//	 */
//	public static void main(String arg[]) throws NetException {
//		/*
//		 * LocationCTLPacket lp = new LocationCTLPacket();
//		 * lp.setLoc_time_interval("1000"); lp.setMac("13141473302");
//		 * lp.setMctl("257"); YAXONEncoder ya = new YAXONEncoder(); // byte
//		 * content[]=ya.encode(lp); // for(int i=0;i<content.length;i++){ //
//		 * System.out.println(content[i]);
//		 * 
//		 * MCTLType mctlType = MCTLType.valueOf("LOCATIONCTL");
//		 * //System.out.println(mctlType.getType());
//		 * System.out.println(MCTLType.getType(1)); switch(MCTLType.getType(1)){
//		 * case LOCATIONCTL: System.out.println("niaho"); break; case
//		 * OVERTIMEALARM: System.out.println("2"); break;
//		 */
//		/* System.out.println(MethodUtil.getDateTime("yyMMddhhmm")); */
//		DTCCTLPacket pc = new DTCCTLPacket(PacketType.DTC);
//		pc.setMctl("010c");
//		pc.setMac("869158001129994");
//		byte[] content = new ZniotEncoder().gprsTrans(pc, null);
//		System.out.println(MethodUtil.toHexString(content));
//	}

}
